package com.lan.app.utils;

import com.lan.ScriptContext;
import com.lan.antlr.ScriptLexer;
import com.lan.antlr.ScriptParser;
import com.lan.evalulate.AstEvaluator;
import com.lan.parse.ParseJslListener;
import com.lan.support.response.json.R;
import lombok.Getter;
import lombok.Setter;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTreeWalker;

@Getter
@Setter
public class Deploy {

    private boolean deploy = false;

    private static Deploy instance;

    public static Deploy getInstance() {
        if (instance == null) {
            instance = new Deploy();
        }
        return instance;
    }


    private ScriptContext context;

    private ScriptLexer lexer;

    private ScriptParser parser;

    public void compile(String script) {
        context = new ScriptContext();
        //词法分析
        lexer = new ScriptLexer(CharStreams.fromString(script));
        CommonTokenStream tokens = new CommonTokenStream(lexer);

        //语法分析
        parser = new ScriptParser(tokens);
//        context.setAst(parser.variableDeclarator());
        context.setAst(parser.prog());
        deploy = true;
    }

    public Object exec() {
        if (!deploy) {
            return null;
        }
        if (context == null) {
            return null;
        }
        //语义分析
        ParseTreeWalker walker = new ParseTreeWalker();
        //多步的语义解析。
        //优点：1.代码更清晰；2.允许使用在声明之前，这在支持面向对象、递归函数等特征时是必须的。
        //pass1：类型和Scope
//        TestScriptBaseListener scopeScanner = new TestScriptBaseListener(context);
//        walker.walk(scopeScanner, context.getAst());
        System.out.println(context.getAst().toStringTree(parser));
        ParseJslListener parseJslListener = new ParseJslListener(context);
        walker.walk(parseJslListener, context.getAst());

        AstEvaluator astEvaluator = new AstEvaluator(context);
        Object result = astEvaluator.visit(context.getAst());
        System.out.println("result:" + result);
        return R.OK(result);
    }


}
